﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using Microsoft.VisualBasic.Devices;

namespace CM
{
	public partial class MainWindow : Window
	{
		#region intialize
		
		public string Path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CM";
		int isserverstart = 0;
		string ServerPath;
        string ram;
        string WorldName;
		string versionfile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CM\version.xml";

		Process craftbukkit = new Process();
		Thread OutputThread;
		Thread ErrorThread;
		
		public MainWindow()
		{
			InitializeComponent();

			#region Check for first time
			if (Properties.Settings.Default.First == false)
			{
				FirstTimeRun();
			}
			#endregion

		}

		#region Firsttime
		private void FirstTimeRun()
		{
			Window First = new FirstTimeSetup();

			First.ShowDialog();
			Properties.Settings.Default.First = false;
		} 
		#endregion

		#endregion

		#region MenuBar

		#region OpenSqLite
		private void OpenSql_Click(object sender, RoutedEventArgs e)
		{
			// TODO: make method OpenSqliteDatabase
		} 
		#endregion

		#region OpenMySql
		private void OpenMySql_Click(object sender, RoutedEventArgs e)
		{
			// TODO: make method OpenMySqlDatabase 
		} 
		#endregion

		#region ResetConfig
		private void ResetConfig_Click(object sender, RoutedEventArgs e)
		{
			//Todo: Reset config
		} 
		#endregion

		#region OpenConfig
		private void OpenConfig_Click(object sender, RoutedEventArgs e)
		{
			Window config = new Config();
			config.Show();
		} 
		#endregion

		#region AboutCM
		private void AboutItem_Click(object sender, RoutedEventArgs e)
		{
			// Open about window
			Window about = new AboutWindow();
			about.Show();
		} 
		#endregion

		private void StartStopServer_Click(object sender, RoutedEventArgs e)
		{
			if (isserverstart == 0)
			{
				Startserver();
				StartStopServerMenu.Header = "Stop Server";
				isserverstart = 1;

				// Will move this later to the actual start server void to avoid it being set to running if start server fails. Just temp testing :)
				// Set status label to running
				lblServerRunning.Content = "Started";
				lblServerRunning.FontWeight = FontWeights.Bold;
				lblServerRunning.Foreground = Brushes.LimeGreen;
			}
			else if (isserverstart == 1)
			{
				Stopserver();
				StartStopServerMenu.Header = "Start Server";
				isserverstart = 0;

				

				// Will move this later to the actual start server void to avoid it being set to running if stop server fails. Just temp testing :)
				// Set status label to not running
				lblServerRunning.Content = "Not running";
				lblServerRunning.FontWeight = FontWeights.Normal;
				lblServerRunning.Foreground = Brushes.Black;

			}
		}

		private void AboutItemBukkit_Click(object sender, RoutedEventArgs e)
		{
			MessageBox.Show("CurrentVersion: More info: http://bukkit.org");
		}

        #region Update
        private void Update_click(object sender, RoutedEventArgs e)
        {
            
            string XmlURL = "http://dl.dropbox.com/u/14545710/version.xml";

            WebClient cl = new WebClient();
            if (File.Exists(Path + @"\version.xml"))
            {
                File.Delete(Path + @"\version.xml");
            }
            cl.DownloadFileAsync(new Uri(XmlURL), Path + @"\version.xml");
            cl.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
        } 

        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            XmlDocument XDoc = new XmlDocument();
            XDoc.Load(Path + @"\version.xml");
            XmlElement El = XDoc.DocumentElement;
            if (Double.Parse(El.ChildNodes[0].InnerText) > Properties.Settings.Default.Version)
            {
                if (MessageBox.Show("There is a new update: " + El.ChildNodes[0].InnerText + " Do you want to update?", "Update Found", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    string DownloadURL = "http://dl.dropbox.com/u/14545710/CM.exe";
                    WebClient wc = new WebClient();
                    wc.DownloadFileAsync(new Uri(DownloadURL), Path + @"\_CM.exe");
                    Process pro = new Process();
                    pro.StartInfo.FileName = Path + @"\Updater.exe";
                }
                else
                {
                    //Do nothing probably
                }
            }
        }
        #endregion

		#endregion

		#region MainWindow

		#region ExitButton
		private void exitbutton_Click(object sender, RoutedEventArgs e)
		{
			// To prevent the warning
			isserverstart = 0;

			Application.Current.Shutdown();
		} 
		#endregion

		#region SendButtonClick
		private void SendButton_Click(object sender, RoutedEventArgs e)
		{
			string cslinput = Sendbox.Text.ToString();
			if (isserverstart == 1)
			{
                craftbukkit.StandardInput.WriteLine(cslinput);
                consolebox.Text += cslinput;
			}
			else
			{
				consolebox.Text += "\nServer is not started!";
			}

		} 
	    #endregion

		#region SendCommandonKey
		private void SendBox_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.Key == Key.Enter)
			{
				if (isserverstart == 1)
				{
					if (Sendbox.Text != null || Sendbox.Text != "")
					{
						craftbukkit.StandardInput.WriteLine(Sendbox.Text);
                        consolebox.Text += "\n" + Sendbox.Text;
						Sendbox.Text = "";
					}
				}
				else
				{
					consolebox.Text += Environment.NewLine + "Server has not been started!";
				}
			}
		} 
	#endregion

		#endregion

		#region Methods

		#region Start and Stop Server

		#region StartServer

		public void Startserver()
		{
			#region Startup

			consolebox.Text = "";
            string otherpath = ServerPath;
			string javapath;
			
			if (Environment.Is64BitOperatingSystem)
			{
				javapath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + @"\java\jre6\bin\java.exe";
			}
			else
			{
				javapath = "java";
			}

			craftbukkit.StartInfo.FileName = "cmd.exe";
			craftbukkit.StartInfo.UseShellExecute = false;
			craftbukkit.StartInfo.ErrorDialog = false;
			craftbukkit.StartInfo.RedirectStandardInput = true;
			craftbukkit.StartInfo.RedirectStandardOutput = true;
			craftbukkit.StartInfo.RedirectStandardError = true;
			craftbukkit.StartInfo.CreateNoWindow = true;
			craftbukkit.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

			#endregion

			#region Startserver
            
			craftbukkit.Start();
            craftbukkit.StandardInput.WriteLine("cd " + ServerPath);
            craftbukkit.StandardInput.WriteLine(javapath + " -Xms" + ram + "M -Xmx" + ram + "M" + " -jar " + "craftbukkit.jar");
			OutputThread = new Thread(new ThreadStart(OutputUpdate));
			OutputThread.IsBackground = true;
			OutputThread.Start();
			ErrorThread = new Thread(new ThreadStart(ErrorUpdate));
			ErrorThread.IsBackground = true;
			ErrorThread.Start();
			
			#endregion
		}
		#endregion

		#region StopServer

		public void Stopserver()
		{
			craftbukkit.StandardInput.WriteLine("stop");
			craftbukkit.Close();
		}
		#endregion

		#region console updater

		void OutputUpdate()
		{
            while (!craftbukkit.StandardOutput.EndOfStream)
            {
                if (craftbukkit.StandardOutput.ReadLine() == "")
                {
                    this.Dispatcher.Invoke((Action)(() =>
                    {
                        consolebox.Text += "\n" + craftbukkit.StandardOutput.ReadLine();
                        consolebox.ScrollToEnd();
                    }));
                }
                Thread.Sleep(1000);
            }
		}

		void ErrorUpdate()
		{
			
		}

		#endregion

		#endregion

		#region OpenMysql

		//Todo: code for MySql

		#endregion

		#region OpenSQLite

		//Todo: code for SQLite

		#endregion

		#endregion

		#region CM Load

		private void CM_Loaded(object sender, RoutedEventArgs e)
		{
			#region Checkfolder

			if (!Directory.Exists(Path))
			{
				Directory.CreateDirectory(Path);
			}

			#endregion

			#region Download

			if (File.Exists(Path + @"\configuration.xml"))
			{
				XmlDocument Doc = new XmlDocument();
				Doc.Load(Path + @"\configuration.xml");
				XmlElement Element = Doc.DocumentElement;
				ServerPath = Element.ChildNodes[0].InnerText;
                WorldName = Element.ChildNodes[8].InnerText;
                ram = Element.ChildNodes[1].InnerText;
			}
			else
			{
				WebClient WC = new WebClient();
				WC.DownloadFile(new Uri("http://dl.dropbox.com/u/14545710/configuration.xml"), Path + @"\configuration.xml");
				XmlDocument Doc = new XmlDocument();
				Doc.Load(Path + @"\configuration.xml");
				XmlElement Element = Doc.DocumentElement;
				ServerPath = Element.ChildNodes[0].InnerText;
                ram = Element.ChildNodes[1].InnerText;
                WorldName = Element.ChildNodes[8].InnerText;
			}

			#endregion

			#region ResolutionCheck
			// Warn users with low resolution
			if (System.Windows.SystemParameters.PrimaryScreenWidth < 1024 | System.Windows.SystemParameters.PrimaryScreenHeight < 600)
			{
				MessageBox.Show(@"Your resolution is lower than the recomended resolution for using this program. You will still be able to run it, however the user experience might not be optimal.");
			}
			#endregion

			#region RunStorageCheck

			StorageCheck();

			#endregion

			#region loadPluginConfig

			loadPluginConfig();

			#endregion
		} 

		#endregion

		#region Storage Check
		void StorageCheck()
		{
			Thread GetFolder = new Thread(new ThreadStart(GetCurrentFolderSize));
			GetFolder.IsBackground = true;
			GetFolder.Start();

			Thread GetPreformanceThread = new Thread(new ThreadStart(GetPreformance));
			GetPreformanceThread.IsBackground = true;
			GetPreformanceThread.Start();
		} 
	#endregion

		#region Protected Performance Counter
		protected PerformanceCounter ramCounter;
		protected PerformanceCounter CPUcounter; 
		#endregion

		#region GetFreeMemory
		public long GetFreeMemory()
		{
			PerformanceCounter Ram = new PerformanceCounter("Memory", "Available Bytes");
			long FreeRAMByte = Convert.ToInt64(Ram.NextValue());
			long FreeRAMKB = FreeRAMByte / 1024;
			long FreeRAM = FreeRAMKB / 1024;

			return FreeRAM;
		} 
	#endregion

		#region GetTotalCPU
		public string GetTotalCPU
		{
			get
			{
				CPUcounter = new PerformanceCounter();

				CPUcounter.CategoryName = "Processor";
				CPUcounter.CounterName = "% Processor Time";
				CPUcounter.InstanceName = "_Total";

				return CPUcounter.NextValue().ToString();
			}
		} 
	#endregion

		#region GetPerformance
		void GetPreformance()
		{
			while (true)
			{
					string Ram = GetFreeMemory().ToString();
					string CPU = GetTotalCPU.ToString();

					this.Dispatcher.Invoke((Action)(() =>
					{
						lblCpuUsage.Content = CPU + "%";
						lblRamAvalible.Content = Ram + "mb";
					}));

					Thread.Sleep(3000);
			}
		} 
	    #endregion

		#region GetFolderSize
		void GetCurrentFolderSize()
		{
			if (ServerPath == null || ServerPath == "")
			{
				MessageBox.Show("No Server folder Specified", "No server Folder");
			}
			else
			{
				DirectoryInfo di = new DirectoryInfo(ServerPath);
				FileInfo[] files = di.GetFiles("*", SearchOption.AllDirectories);
				long size = 0;
				foreach (FileInfo fi in files)
				{
					size += fi.Length;
				}

				long sizeKB = size / 1024;
				long sizeMB = sizeKB / 1024;

				this.Dispatcher.Invoke((Action)(() =>
				{
					progressBarStorage.Value = int.Parse(sizeMB.ToString());
					lblUsingMb.Content = sizeMB.ToString() + "mb";
					lblStoragePath.Text = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\BSM";
				}));
			}
		} 
		#endregion

		#region closeFailSafe

		#region CMClosing
		private void CM_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{

			// Ask for confirmation to close the window while the server is running

			if (isserverstart == 1)
			{
				// Please do not edit the string in message box show
				if (MessageBox.Show(@"The server is currently running. Closing this window will kill the server.
				Do you really want to close this window?",
				"Warning", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
				{
                    Stopserver();
				}
				else
				{
					e.Cancel = true;
				}
			}

		} 
		#endregion

		#endregion

		#region PluginConfig

		#region LoadPluginCofig
		void loadPluginConfig()
		{
			// Load the installed plugin component

			Thread loadPluginConf = new Thread(new ThreadStart(loadInstalledPlugins));
			loadPluginConf.IsBackground = true;
			loadPluginConf.Start();
		} 
		#endregion

		#region LoadInstalledPlugins
		void loadInstalledPlugins()
		{
			try
			{
				//Load installed plugins component
				string AppData = ServerPath + @"\plugins";
				System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(AppData);
				foreach (System.IO.FileInfo f in dir.GetFiles("*.jar"))
				{
					string plugin = f.Name.Substring(0, f.Name.Length - 4);
					this.Dispatcher.Invoke((Action)(() =>
					{
						listBox1.Items.Add(plugin);
					}));
				}
			}
			catch (Exception ex)
			{
				if (ex.ToString().Substring(0, 9) == "System.IO")
				{
					if (MessageBox.Show("Seemingly there is no plugin folder in the server path. Do you want it to be created",
						"Plugin folder",
						MessageBoxButton.YesNo) == MessageBoxResult.Yes)
					{
						Directory.CreateDirectory(ServerPath + @"\plugins");
						MessageBox.Show("Created folder: " + ServerPath + @"\plugins");
					}
					else
					{
						MessageBox.Show("Why not??");
					}
				}
				else
				{
					MessageBox.Show(@"Fatal error occured, please report this to the CM team (google print screen for screenshot): " + ex.ToString());
				}
			}
		} 
		#endregion

		#region LoadFile
		void openFile()
		{
			try
			{
				// Create OpenFileDialog 
				Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

				dlg.DefaultExt = ".yml";
				dlg.InitialDirectory = ServerPath + @"\plugins";
				dlg.Filter = "Yml - Configuration file (*.yml)|*.yml|TXT files (*.txt)|*.txt|Properties file (*.properties)|*.properties|Xml Files (*.xml)|*.xml";

				// Display OpenFileDialog
				Nullable<bool> result = dlg.ShowDialog();

				dlg.InitialDirectory = ServerPath;

				// Get the selected file
				if (result == true)
				{
					lblManLoad.Visibility = Visibility.Hidden;
					string filename = dlg.FileName;

					if (filename.Length > 0)
					{
						openFile(filename);
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(@"Something went wrong loading your file.
				The exact error code is:
				" + ex);
			}
		} 
		#endregion

		#region ClickEvents
		private void Open_Click(object sender, RoutedEventArgs e)
		{
			openFile();
		}

		private void Save_Click(object sender, RoutedEventArgs e)
		{
			saveFile();
		} 
		#endregion

		#region SaveandOpen
		void saveFile()
		{
			if (lblEditing.Content.ToString() != "None")
			{
				File.WriteAllText(lblEditing.Content.ToString(), EditTextbox.Text);
				Save.IsEnabled = false;
			}
		}

		private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
		{
			Save.IsEnabled = true;
		}

		void openFile(string FilePath)
		{
			lblEditing.Content = FilePath;

			EditTextbox.Text = File.ReadAllText(FilePath);
			lblManLoad.Visibility = Visibility.Hidden;

			if (FilePath.Substring(FilePath.Length - 4, 4) == ".yml")
			{
				EditTextbox.AcceptsTab = false;
			}
			else
			{
				EditTextbox.AcceptsTab = true;
			}
		} 
		#endregion

		#region FetchFiles
		void fetchConfigFiles()
		{

            bool FileOpened = false;
			// If it fails, then don't do anything
			try
			{
				EditTextbox.Text = "";
				string plugin = listBox1.SelectedItem.ToString();

				if (plugin.Contains("MinecartMania"))
				{
                    try
                    {
                        string mmpath = ServerPath + @"\plugins\MinecartMania\";
                        string filename = "";
                        DirectoryInfo Dir = new DirectoryInfo(mmpath);
                        FileInfo[] fis = Dir.GetFiles("*.xml");
                        if (plugin.Contains("Core") || plugin.Contains("core"))
                        {
                            filename = mmpath + "MinecartManiaConfiguration.xml";
                        }
                        else
                        {
                            foreach (FileInfo fi in fis)
                            {
                                if (fi.Name.Contains(plugin))
                                {
                                    filename = fi.FullName;
                                }
                            }
                        }
                        if (filename == "")
                        {
                            FileOpened = false;
                        }
                        else
                        {
                            StreamReader Reader = new StreamReader(filename);
                            EditTextbox.Text = Reader.ReadToEnd();
                            Reader.Close();
                            FileOpened = true;
                        }
                    }
                    catch (Exception)
                    {
                        FileOpened = false;
                    }
				}
                else if (plugin.Contains("MagicCarpet"))
                {
                    try
                    {
                        StreamReader Reader = new StreamReader(ServerPath + @"\magiccarpet.properties");
                        EditTextbox.Text = Reader.ReadToEnd();
                        Reader.Close();
                        FileOpened = true;
                    }
                    catch (Exception)
                    {
                        FileOpened = false;
                    }
                }
                else
                {
                    try
                    {
                        DirectoryInfo Dir = new DirectoryInfo(ServerPath + @"\plugins\" + plugin);
                        if (!Dir.Exists)
                        {
                            FileOpened = false;
                        }
                        else
                        {
                            foreach (FileInfo fi in Dir.GetFiles())
                            {
                                if (fi.Extension == ".properties")
                                {
                                    StreamReader Reader = new StreamReader(fi.FullName);
                                    EditTextbox.Text = Reader.ReadToEnd();
                                    Reader.Close();
                                    FileOpened = true;
                                    break;
                                }
                                if (fi.Extension == ".yml" || fi.Extension == ".xml" || fi.Extension == ".settings")
                                {
                                    if (Dir.GetFiles("*.*").Length > 1)
                                    {
                                        if (fi.Name.Contains("config") || fi.Name.Contains("Config") || fi.Name.Contains("settings") || fi.Name.Contains("iConomy") 
                                            || fi.Name.Contains(WorldName) || fi.Name.Contains("properties") || fi.Name.Contains("config"))
                                        {
                                            StreamReader Reader = new StreamReader(fi.FullName);
                                            EditTextbox.Text = Reader.ReadToEnd();
                                            Reader.Close();
                                            FileOpened = true;
                                            break;
                                        }
                                        else
                                        {
                                            FileOpened = false;
                                        }
                                    }
                                    else
                                    {
                                        StreamReader Reader = new StreamReader(fi.FullName);
                                        EditTextbox.Text = Reader.ReadToEnd();
                                        Reader.Close();
                                        FileOpened = true;
                                        break;
                                    }
                                }
                            }
                        }
                        
                    }
                    catch (Exception)
                    {
                        FileOpened = false;
                    }
                }

                if (FileOpened == false)
                {
                    FailedLabel.Visibility = Visibility.Visible;
                }
                else
                {
                    FailedLabel.Visibility = Visibility.Hidden;
                }
			}
			catch
			{
				lblManLoad.Visibility = Visibility.Visible;
				lblEditing.Content = "None";
				EditTextbox.Text = "";
			}
		} 
		#endregion

		#region SelectionChangedPluginList
		private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			if (listBox1.SelectedItem.ToString().Length > 0)
			{
				fetchConfigFiles();
			}
		} 
		#endregion

		#endregion

		#region OpenFolders

		#region OpenServerFolder
		private void OServerFolder_Click(object sender, RoutedEventArgs e)
		{
			Process proc = new Process();
			proc.StartInfo.FileName = "explorer.exe";
			proc.StartInfo.Arguments = ServerPath;
			proc.Start();
		}
		#endregion

		#endregion
	}
}
